function DataBinder(object_id){
	const data_attr = `bind-${object_id}`,
		msg = `${object_id}:change`;
	// document.body.dispatchEvent(evt)
	document.body.addEventListener('change', (evt) => {
		const input = evt.target;
		document.body.dispatchEvent(eventClone, {
			attr_name: input.getAttribute(data_attr),
			val: input.value
		})
	}, false);

	let detail = {initiator: ''}
	const evt = new CustomEvent(msg, { detail });
	const eventClone = new evt.constructor(evt.type, evt)
	const domPubSub = document.body;
	let dataPubSub = {
		callbacks: {},
		on: function(msg, callback){
		    this.callbacks[msg] = this.callbacks[msg] || [];
		    this.callbacks[msg].push(callback);
		},
		publish: function(msg, detail){
		    this.callbacks[msg] = this.callbacks[msg] || [];
		    for(var i = 0, len = this.callbacks[msg].length; i<len; i++){
		        this.callbacks[msg][i].apply(this, detail);
		    }
		}
	}

	let current_attrName = '', current_val = '';

	// view监听 - 对每个dom进行change监听
	Array.from(document.querySelectorAll(`[data-${data_attr}`)).map(input => {
		input.addEventListener('change', (e) => {
			const input = e.target;
			current_attrName = input.getAttribute(`data-${data_attr}`);
			current_val = input.value;
			detail.initiator = 'view'
			// domPubSub.dispatchEvent(eventClone)
			dataPubSub.publish('view')
		}, false);
	})
	// data监听
	// 呀！这是defineObj出现以前的做法呀！
	let data = {
		attributes: {},
		set: function(attr_name, val){
			this.attributes[attr_name] = val;
			current_attrName = attr_name;
			current_val = val;
			console.log('我被set了！')
			detail.initiator = 'data'
			// domPubSub.dispatchEvent(eventClone);
			dataPubSub.publish('data')
		},
		get: function(attr_name, val){
			return this.attributes[attr_name];
		}
	}

	domPubSub.addEventListener(msg, (e) => {
		// trigger view
		if(e.detail.initiator === 'data') {
			console.log('监听到data变化，更新view')
			const sameDoms = document.querySelectorAll(`[data-${data_attr} = ${current_attrName}]`);
			for(let i = sameDoms.length-1; i>=0; i--){
				const thisDom = sameDoms[i];
				if(['INPUT','TEXTAREA','SELECT'].indexOf(thisDom.tagName) >= 0) thisDom.value = current_val;
				else this.Dom.textContent = current_val;
			}
		}
		// trigger data
		if(e.detail.initiator === 'view') {
			console.log('监听到view变化，更新data')
			data.attributes[current_attrName] = current_val;
		}
	}, false)

	dataPubSub.on('data', () => {
		console.log('监听到data变化，更新view')
		const sameDoms = document.querySelectorAll(`[data-${data_attr} = ${current_attrName}]`);
		for(let i = sameDoms.length-1; i>=0; i--){
			const thisDom = sameDoms[i];
			if(['INPUT','TEXTAREA','SELECT'].indexOf(thisDom.tagName) >= 0) thisDom.value = current_val;
			else this.Dom.textContent = current_val;
		}
	})
	dataPubSub.on('view', () => {
		console.log('监听到view变化，更新data')
		data.attributes[current_attrName] = current_val;
	})

	return data;
}

let d1 = new DataBinder(123);
d1.set('name', 'bpppm');
d1.set('age', 20)
let d2 = new DataBinder(223);
d2.set('name', 'sssss');
d2.set('age', 25)
document.querySelector('#test').onclick = () => console.log(d1.attributes);